package io.gitee.zhangbinhub.admin.oauth.conf

import cn.dev33.satoken.oauth2.config.SaOAuth2ServerConfig
import cn.dev33.satoken.oauth2.consts.GrantType
import cn.dev33.satoken.oauth2.consts.SaOAuth2Consts
import cn.dev33.satoken.oauth2.data.model.loader.SaClientModel
import cn.dev33.satoken.oauth2.strategy.SaOAuth2Strategy
import com.fasterxml.jackson.databind.ObjectMapper
import io.gitee.zhangbinhub.admin.oauth.authentication.UserPasswordGrantTypeHandler
import io.gitee.zhangbinhub.admin.oauth.constant.OauthConstant
import io.gitee.zhangbinhub.admin.oauth.service.ApplicationService
import org.springframework.cloud.client.loadbalancer.LoadBalanced
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter
import org.springframework.web.client.RestClient

@Configuration
class AcpOauthServerAutoConfiguration(
    private val objectMapper: ObjectMapper,
    private val applicationService: ApplicationService,
    private val saOAuth2ServerConfig: SaOAuth2ServerConfig, userPasswordGrantTypeHandler: UserPasswordGrantTypeHandler,
) {
    init {
        SaOAuth2Consts.Api.authorize = "/inner/oauth/authorize"
        SaOAuth2Consts.Api.token = "/inner/oauth/token"
        SaOAuth2Consts.Api.refresh = "/inner/oauth/refresh"
        SaOAuth2Consts.Api.revoke = "/inner/oauth/revoke"
        SaOAuth2Consts.Api.client_token = "/inner/oauth/client_token"
        SaOAuth2Consts.Api.doLogin = "/inner/oauth/doLogin"
        SaOAuth2Consts.Api.doConfirm = "/inner/oauth/doConfirm"
        SaOAuth2Strategy.instance.registerGrantTypeHandler(userPasswordGrantTypeHandler)
    }

    fun loadClientInfo() {
        applicationService.getAppList().map { application ->
            SaClientModel()
                .setClientId(application.id)
                .setClientSecret(application.secret)
                .setClientTokenTimeout(application.accessTokenValiditySeconds.toLong()) // 单位秒
                .setAccessTokenTimeout(application.accessTokenValiditySeconds.toLong()) // 单位秒
                .setRefreshTokenTimeout(application.refreshTokenValiditySeconds.toLong()) // 单位秒
                .addContractScopes(*(application.scope ?: "").split(",").toTypedArray())
                .addAllowGrantTypes(
                    GrantType.client_credentials,
                    GrantType.refresh_token,
                    OauthConstant.granterUserPassword
                )
        }.associateBy { it.clientId }.apply {
            saOAuth2ServerConfig.setClients(this)
        }
    }

    @Bean("acpSpringCloudResourceServerRestClientBuilder")
    @LoadBalanced
    fun oauthRestClientBuilder(): RestClient.Builder = RestClient.builder()
        .messageConverters { messageConverters ->
            messageConverters.add(MappingJackson2HttpMessageConverter(objectMapper))
        }
}